package com.z.security.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.List;

/**
 * @author zhaodf
 */
@Configuration
public class SecurityConfig {

    @Bean
    UserDetailsService us() {
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
//        创建内存中的用户
        manager.createUser(User.withUsername("zs").password("{noop}1234").roles("admin").build());
        return manager;
    }

    /**
     * 配置过滤器链
     * @return
     */
//    @Bean
//    SecurityFilterChain securityFilterChain() {
////      拦截所有请求,并且不经过任何过滤器
//        return new DefaultSecurityFilterChain(new AntPathRequestMatcher("/**"));
//
//    }

    WebSecurityCustomizer webSecurityCustom(){
        return web -> web.ignoring().requestMatchers("/hello2");
    }

    /**
     * 保存的默认的过滤器的配置
     *
     * @param http
     * @return
     */
    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        //                           拿到了request, 就可以进行服务端跳转
//                           拿到了response, 就可以进行服务端跳转
//                          authentication,里面也有登录成功的用户信息
        http

//                所有请都要验证之后才可以访问
                .authorizeHttpRequests(a ->
                        a.requestMatchers("/hello2")
//                       登录或者不登陆都能访问
                        .permitAll()
                        .anyRequest()
                        .authenticated())
//                配置表单登录
                .formLogin(f -> f.usernameParameter("username").passwordParameter("password")
//                        登录页面 不配置,默认就是/login  (GET)
                        .loginPage("/login.html")
//                         登录接口,不配置默认就是/login   (POST)
                        .loginProcessingUrl("/login")
//                        登录之后的跳转页面, 这个是服务端跳转,不推荐
//                         服务端跳转,浏览器地址不改变,用户刷新会重新提交表单(比如重新登录)
                        .successForwardUrl("/hello")
//                        客户端跳转.第二个参数表示是否总是用这个地址跳转
//                        默认情况下,如果访问存在缓存的请求,则登录成功之后就会跳转到缓存的地址,否则才会跳转到这个
//                        如果第二个参数为true,则不考虑缓存的请求.登录成功之后,都跳转到这里指定的地址.
//                        .defaultSuccessUrl("/hello")
//                        自定义登录成功的处理器
//                        .successHandler((request, response, authentication) -> {
//                            Object principal = authentication.getPrincipal();
//                            ObjectMapper om = new ObjectMapper();
//                            String s = om.writeValueAsString(principal);
//                            response.setContentType("application/json;charset=utf-8");
//                            response.getWriter().write(s);
//                        })
//                        登录失败的的服务端跳转.
//                        .failureForwardUrl()
//                        登录失败客户端跳转
//                        .failureUrl()
//                         集大成者
                        .failureHandler((request, response, exception) -> {
                            response.getWriter().write("error");
                        })
                        .permitAll())
                .logout(l -> l
                        .logoutRequestMatcher(new OrRequestMatcher(
                                new AntPathRequestMatcher("/logout1", "GET"),
                                new AntPathRequestMatcher("/logout2", "POST")
                        ))
//                        注销登录的地址
//                        .logoutUrl("/logout")
                        .defaultLogoutSuccessHandlerFor((request, response, authentication) -> {
                            response.getWriter().write("logout1-logout");
                        }, new AntPathRequestMatcher("/logout1", "GET"))
                        .defaultLogoutSuccessHandlerFor((request, response, authentication) -> {
                            response.getWriter().write("logout2-logout");
                        }, new AntPathRequestMatcher("/logout2", "POST"))
//                        销毁session,默认就是true
                        .invalidateHttpSession(true)
//                        清除cookie
                        .deleteCookies()
//                        清除认证信息
                        .clearAuthentication(true)
//                        注销成功之后的跳转页面
//                        .logoutSuccessUrl("/login.html")

                        .permitAll())
//                关闭csrf校验,本质就是从过滤器链移除csrf过滤器
                .csrf(c -> c.disable());
        return http.build();

    }


}
